/*
 * Copyright (c) 2011 Imre Fazekas.
 *  All rights reserved.
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice, this
 *  list of conditions and the following disclaimer.
 *
 *  Redistributions in binary form must reproduce the above copyright notice,
 *  this list of conditions and the following disclaimer in the documentation
 *  and/or other materials provided with the distribution.
 *  Neither the name of the Brillien nor the names of its
 *  terms and concepts may be used to endorse or promote products derived from this
 *  software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 */

package com.vii.brillien.core.component.websocket;

import com.vii.brillien.core.component.apikey.ApiKeyValidatorPresence;
import com.vii.brillien.core.component.sso.SubjectPresence;
import com.vii.brillien.core.management.BrillienServices;
import com.vii.brillien.ignition.transport.BrillienCommunication;
import com.vii.brillien.kernel.BrillienException;
import com.vii.streamline.services.error.StreamLineException;
import org.glassfish.grizzly.http.HttpRequestPacket;
import org.glassfish.grizzly.websockets.WebSocketApplication;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public abstract class BrillienWebSocketApplication extends WebSocketApplication {

    protected String                    serviceContext;
    protected Logger                    logger;

    protected boolean                   ssoRequired;
    protected SubjectPresence           ssoPresence;
    protected boolean                   apiKeyRequired;
    protected ApiKeyValidatorPresence   apiKeyValidator;

    protected String                    deploymentName;

    {
        logger              = LoggerFactory.getLogger(this.getClass());
        deploymentName      = this.getClass().getSimpleName();
    }

    public String getServiceContext() {
        return serviceContext;
    }

    public void setServiceContext(String serviceContext) {
        this.serviceContext = serviceContext;
    }

    public String getDeploymentName() {
        return deploymentName;
    }

    public void setDeploymentName(String deploymentName) {
        this.deploymentName = deploymentName;
    }

    @Override
    public boolean isApplicationRequest(HttpRequestPacket request) {
        return serviceContext.equals(request.getRequestURI());
    }

    protected SubjectPresence getSSOPresence() throws BrillienException {
        return BrillienServices.<SubjectPresence>getPresenceByName(BrillienServices.liaison, BrillienServices.liaison.getSSOPresenceName());
    }

    protected ApiKeyValidatorPresence getApiKeyValidator() throws BrillienException {
        return BrillienServices.<ApiKeyValidatorPresence>getPresenceByName( BrillienServices.liaison, BrillienServices.liaison.getApiKeyPresenceName() );
    }

    protected boolean checkApiKeyRequired(){
        return  apiKeyRequired = BrillienServices.liaison != null && BrillienServices.liaison.getApiKeyPresenceName() != null;
    }

    protected boolean checkSsoRequired(){
        return  ssoRequired = BrillienServices.liaison != null && BrillienServices.liaison.getSSOPresenceName() != null;
    }

    protected void checkCallPermissions(BrillienCommunication comm) throws BrillienException {
        if( ssoRequired && comm.getSession() == null )
            throw new BrillienException( StreamLineException.ERROR_INVALID_CREDENTIALS, "Not authenticated!");
    }

    protected void checkCallPreconditions(BrillienCommunication comm) throws BrillienException {
        if( apiKeyRequired && (comm.getApiKey() == null || !apiKeyValidator.isValid( comm.getApiKey() ) ) )
            throw new BrillienException( StreamLineException.ERROR_INVALID_CREDENTIALS, "API_KEY is required!");
    }

    public void initWebSocketApplication() throws BrillienException{
        ssoRequired = checkSsoRequired();
        if( ssoRequired )
            try {
                ssoPresence = getSSOPresence();
            } catch (BrillienException e) {
                ssoRequired = false;
                throw e;
            }

        apiKeyRequired = checkApiKeyRequired();
        if( apiKeyRequired )
            try {
                apiKeyValidator = getApiKeyValidator();
            } catch (BrillienException e) {
                apiKeyRequired = false;
                throw e;
            }
    }

}
